package com.sxj.corejava.util;

import java.io.*;

/**
 * @author 石小俊
 * 2024年07月29日 11:11
 */
public class FileUtil {

    /**
     * 拷贝文件
     * @param src    源文件
     * @param target 目标文件
     */
    public static void copyFile(File src, File target) throws IOException {
        try (
                FileInputStream in = new FileInputStream(src);
                FileOutputStream out = new FileOutputStream(target)
        ) {
            // 从src中读取内容
            byte[] b = new byte[1024];
            int i = -1;
            while ((i = in.read(b)) != -1) {
                out.write(b, 0, i);
            }
            System.out.println("提示:文件拷贝成功!");
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 拷贝文件
     * @param src    源文件
     * @param target 目标文件
     */
    public static void copyFile(String src, String target) throws IOException {
        copyFile(new File(src), new File(target));
    }

    /**
     * 将一个目录中所有的文件拷贝到指定目录中
     * @param src
     * @param target
     */
    public static void copyDirectory(String src, String target) throws IOException {
        File srcFile = new File(src);
        File targetFile = new File(target);
        // 目标目录可能不存在,可以创建对应目录
        targetFile.mkdirs();

        // 取出源目录中所有文件
        File[] files = srcFile.listFiles();
        for (File file : files) {
            // 判断当前迭代的是否是文件
            if (file.isFile()) {
                // 如果是文件,则拷贝
                copyFile(file, new File(target + File.separator + file.getName()));
            }
        }
    }

    /**
     * 将一个目录中的文件与子目录递归拷贝到一个指定的目录中
     * @param src
     * @param target
     */
    public static void recursiveCopy(String src, String target) throws IOException {
        File srcFile = new File(src);
        File targetFile = new File(target);
        // 创建目标目录
        targetFile.mkdirs();
        // 获取源文件中所有资源
        File[] files = srcFile.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                // 如果是目录,则递归操作
                recursiveCopy(file.getAbsolutePath(), target + File.separator + file.getName());
            } else {
                // 如果是文件,则直接复制
                copyFile(file, new File(target, file.getName()));
            }
        }
    }

    /**
     * 拆分文件,将一个文件按照指定大小拆分成多个文件,每一个文件名字为:原名字_index,index从1开始,每次自增1
     * 一个输入流,多个输出流,在输出时,每循环一次,输出一个子文件
     * @param path
     * @param length
     */
    public static void splitFile(String path, int length) {

        FileOutputStream out = null;
        try (
                FileInputStream in = new FileInputStream(path);
        ) {
            // 按指定长度进行读取
            byte[] b = new byte[length];
            int i = -1;
            // 定义index初始值
            int index = 1;
            while ((i = in.read(b)) != -1) {
                // 此时每次读取length字节
                // 每次读取完之后写入一个新文件中
                // 因此,每次写入操作对应一个输出流
                out = new FileOutputStream(path + "_" + index++);
                out.write(b, 0, i);
                // 每次输出完成之后,当前输出流用不到了
                // 因此,可以关闭输出流
                out.close();
            }
            System.out.println("文件拆分完成");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 合并文件,将之前拆分的文件合并为一个文件,将子文件的_index部分删除作为文件名
     * 一个输出流,多个输入流
     * @param path
     */
    public static void mergeFile(String path) {
        try {
            // 由于传入的参数中带有_index部分
            // 需要将这部分的内容截取掉
            path = path.substring(0, path.lastIndexOf("_"));
            // 定义一个输出流
            FileOutputStream out = new FileOutputStream(path);

            // 定义多个输入流
            // 输入流中涉及的文件名字与传递的文件名格式一致
            int index = 1;
            // 判断指定文件是否存在
            File file = null;
            while ((file = new File(path + "_" + index++)).exists()) {
                // 每存在一个文件,定义一个输入流
                FileInputStream in = new FileInputStream(file);
                coryStream(in, out);
                // 关闭当前输入流
                in.close();
            }
            System.out.println(path + "文件合并成功");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void coryStream(FileInputStream in, FileOutputStream out) throws IOException {
        byte[] b = new byte[1024 * 1024 * 100];
        int i = -1;
        while ((i = in.read(b)) != -1) {
            out.write(b, 0, i);
        }
    }

    /**
     * 文件加密,读取文件中的每一个字节,根据指定的密码对其进行加密,加密后的文件添加.sec后缀
     * 按字节读取,每个字节通过异或操作实现加密
     * a.txt --> a.txt.sec
     * @param file
     * @param password
     */
    public static void encoded(File file, int password) {
        try (
                FileInputStream in = new FileInputStream(file);
                FileOutputStream out = new FileOutputStream(file.getAbsoluteFile() + ".sec");
        ) {
            int i = -1;
            while ((i = in.read()) != -1) {
                out.write(i ^ password);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件解密,读取加密后的文件中的每一个字节,根据指定的密码对其进行解密,解密后的文件去除.sec后缀
     * 按字节读取,每个字节通过异或操作实现解密
     * a.txt.sec --> a.txt
     * @param file
     * @param password
     */
    public static void decoded(File file, int password) {
        try (
                FileInputStream in = new FileInputStream(file);
                FileOutputStream out = new FileOutputStream(file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")));
        ) {
            int i = -1;
            while ((i = in.read()) != -1) {
                out.write(i ^ password);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
